package com.example.fileupload.storage;

import lombok.extern.slf4j.Slf4j;

import java.io.InputStream;
import java.util.List;
import java.util.Optional;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;

/**
 * 存储策略抽象基类 - 模板方法模式 + 函数式编程
 */
@Slf4j
public abstract class AbstractStorageStrategy implements StorageStrategy {
    
    /**
     * 模板方法：存储分片
     * 定义统一的处理流程，具体步骤由子类实现
     */
    @Override
    public final StorageResult storeChunk(String chunkPath, InputStream inputStream, long size) {
        try {
            // 验证路径
            if (!validatePath().test(chunkPath)) {
                return StorageResult.failure("无效的文件路径: " + chunkPath);
            }
            
            // 前置处理
            Optional<String> preResult = preStoreChunk(chunkPath, inputStream, size);
            if (!preResult.isPresent()) {
                return StorageResult.failure("存储前置处理失败");
            }
            
            // 实际存储
            StorageResult storeResult = doStoreChunk(preResult.get(), inputStream, size);
            if (!storeResult.isSuccess()) {
                return storeResult;
            }
            
            // 后置处理
            return postStoreChunk(storeResult)
                    .orElse(StorageResult.failure("存储后置处理失败"));
            
        } catch (Exception e) {
            return handleStoreError(e);
        }
    }
    
    /**
     * 模板方法：合并文件分片
     */
    @Override
    public final StorageResult mergeChunks(String finalPath, java.util.List<String> chunkPaths, long totalSize) {
        try {
            // 验证路径
            if (!validatePath().test(finalPath)) {
                return StorageResult.failure("无效的文件路径: " + finalPath);
            }
            
            // 前置处理
            Optional<String> preResult = preMergeChunks(finalPath, chunkPaths, totalSize);
            if (!preResult.isPresent()) {
                return StorageResult.failure("合并前置处理失败");
            }
            
            // 实际合并
            StorageResult mergeResult = doMergeChunks(preResult.get(), chunkPaths, totalSize);
            if (!mergeResult.isSuccess()) {
                return mergeResult;
            }
            
            // 后置处理
            return postMergeChunks(mergeResult)
                    .orElse(StorageResult.failure("合并后置处理失败"));
            
        } catch (Exception e) {
            return handleMergeError(e);
        }
    }
    
    /**
     * 模板方法：删除文件
     */
    @Override
    public final boolean deleteFile(String path) {
        try {
            if (!validatePath().test(path)) {
                log.error("删除文件失败: 无效路径 {}", path);
                return false;
            }
            
            return doDeleteFile(path);
            
        } catch (Exception e) {
            log.error("删除文件失败: {}, 错误: {}", path, e.getMessage());
            return false;
        }
    }
    
    /**
     * 模板方法：删除分片文件
     */
    @Override
    public boolean deleteChunks(List<String> chunkPaths) {
        try {
            if (chunkPaths == null || chunkPaths.isEmpty()) {
                return true;
            }
            
            return chunkPaths.stream()
                    .allMatch(this::doDeleteFile);
                    
        } catch (Exception e) {
            log.error("删除分片文件失败: {}", e.getMessage());
            return false;
        }
    }
    
    // ============ 钩子方法 - 子类可以重写 ============
    
    /**
     * 存储前置处理（钩子方法）
     */
    protected Optional<String> preStoreChunk(String chunkPath, InputStream inputStream, long size) {
        log.debug("准备存储分片: {}, 大小: {}", chunkPath, size);
        return Optional.of(chunkPath);
    }
    
    /**
     * 存储后置处理（钩子方法）
     */
    protected Optional<StorageResult> postStoreChunk(StorageResult result) {
        log.debug("分片存储完成: {}", result.getPath());
        return Optional.of(result);
    }
    
    /**
     * 合并前置处理（钩子方法）
     */
    protected Optional<String> preMergeChunks(String finalPath, java.util.List<String> chunkPaths, long totalSize) {
        log.debug("准备合并文件: {}, 分片数: {}", finalPath, chunkPaths.size());
        return Optional.of(finalPath);
    }
    
    /**
     * 合并后置处理（钩子方法）
     */
    protected Optional<StorageResult> postMergeChunks(StorageResult result) {
        log.debug("文件合并完成: {}", result.getPath());
        return Optional.of(result);
    }
    
    // ============ 抽象方法 - 子类必须实现 ============
    
    /**
     * 实际存储分片操作
     */
    protected abstract StorageResult doStoreChunk(String chunkPath, InputStream inputStream, long size);
    
    /**
     * 实际合并分片操作
     */
    protected abstract StorageResult doMergeChunks(String finalPath, java.util.List<String> chunkPaths, long totalSize);
    
    /**
     * 实际删除文件操作
     */
    protected abstract boolean doDeleteFile(String path);
    
    // ============ 通用工具方法 ============
    
    /**
     * 路径验证谓词
     */
    protected Predicate<String> validatePath() {
        return path -> path != null && !path.trim().isEmpty();
    }
    
    /**
     * 存储错误处理
     */
    protected StorageResult handleStoreError(Throwable throwable) {
        log.error("存储分片失败: {}", throwable.getMessage(), throwable);
        return StorageResult.failure("存储失败: " + throwable.getMessage());
    }
    
    /**
     * 合并错误处理
     */
    protected StorageResult handleMergeError(Throwable throwable) {
        log.error("合并文件失败: {}", throwable.getMessage(), throwable);
        return StorageResult.failure("合并失败: " + throwable.getMessage());
    }
    
    /**
     * 安全执行操作 - 函数式错误处理
     */
    protected <T> Optional<T> safeExecute(Supplier<T> supplier, String operation) {
        try {
            log.debug("开始执行: {}", operation);
            T result = supplier.get();
            log.debug("执行成功: {}", operation);
            return Optional.ofNullable(result);
        } catch (Exception e) {
            log.error("执行失败: {} - {}", operation, e.getMessage());
            return Optional.empty();
        }
    }
    
    /**
     * 安全执行操作，抛出异常版本
     */
    protected <T> T safeExecuteOrThrow(Supplier<T> supplier, String operation) {
        try {
            log.debug("开始执行: {}", operation);
            T result = supplier.get();
            log.debug("执行成功: {}", operation);
            return result;
        } catch (Exception e) {
            log.error("执行失败: {} - {}", operation, e.getMessage());
            throw new RuntimeException("执行失败: " + operation, e);
        }
    }
    
    /**
     * 条件执行函数
     */
    protected <T, R> Function<T, Optional<R>> conditionalExecute(
            Predicate<T> condition, 
            Function<T, R> operation,
            Supplier<R> fallback) {
        return input -> condition.test(input) 
                ? Optional.ofNullable(operation.apply(input))
                : Optional.ofNullable(fallback.get());
    }
    
    /**
     * 链式处理函数
     */
    protected <T> Optional<T> pipeline(T input, Function<T, Optional<T>>... operations) {
        Optional<T> current = Optional.ofNullable(input);
        
        for (Function<T, Optional<T>> operation : operations) {
            if (!current.isPresent()) {
                break;
            }
            current = operation.apply(current.get());
        }
        
        return current;
    }
} 